package com.abcd.godating.web;

import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.facebook.api.Facebook;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.abcd.godating.constant.SnsProvider;
import com.abcd.godating.domain.BasicProfile;
import com.abcd.godating.service.ProfileService;
import com.abcd.godating.service.RelationshipService;
import com.abcd.godating.utils.json.JsonMarshaller;
import com.abcd.godating.web.data.FriendLoginData;

/**
 * ../relationship/1  HTTP GET 		=> get user(id=1) relationship
 * ../relationship/1  HTTP DELETE 	=> delete user(id=1) relationship
 * ../relationship/1  HTTP PUT  	=> update user's (id=1) relationship
 * ../relationship    HTTP POST		=> add new user relationship   
 *
 * Json format：
 * [{"UserID":111,"firstName":"tom","lastName":"wang"},{"UserID":222,"firstName":"jack","lastName":"wang"]
 * 
 * @author wangxian
 *
 */
@Controller
@RequestMapping("/relationship/*")
public class RelationshipController {

	private final int DEPTH = 2;

	@Inject
	private RelationshipService relationshipService;
	
	@Inject
	private ProfileService profileService;

	@Inject
	private UsersConnectionRepository usersConnectionRepository;

	@Inject
	private Facebook facebook;

	@RequestMapping(value = "/facebook", method = RequestMethod.GET)
	public @ResponseBody
	Set<Long> facebook(Principal principal) {
		long userId = Long.valueOf(principal.getName());

		List<String> providerUserIds = facebook.friendOperations()
				.getFriendIds();
		Set<String> idStrings = usersConnectionRepository
				.findUserIdsConnectedTo("facebook", new HashSet<String>(
						providerUserIds));
		Set<Long> userIds = new HashSet<Long>(idStrings.size());
		for (String idString : idStrings) {
			userIds.add(Long.parseLong(idString));
		}

		relationshipService.updateFriendShips(userId, SnsProvider.FACEBOOK,
				userIds);
		return relationshipService.getFoaf(userId, SnsProvider.FACEBOOK, DEPTH);
	}
	
	/**
	 * get the current login user's friends
	 */
	@RequestMapping(value = "/userFriend/{userId}", method = RequestMethod.GET)
	public @ResponseBody Collection<FriendLoginData> getFriends(@PathVariable("userId") String userId, HttpServletRequest request, HttpServletResponse response) {
		Collection<FriendLoginData> friendsData = new ArrayList<FriendLoginData>();
		try {
			Long.valueOf(userId);
		} catch (Exception e) {
			return friendsData;
		}
		
		Set<Long> userIds = relationshipService.getFriendShips(Long.valueOf(userId));
		if (CollectionUtils.isNotEmpty(userIds)) {
			Collection<BasicProfile> basicProfiles = profileService.getBasicProfiles(userIds);
			if (CollectionUtils.isNotEmpty(basicProfiles)) {
				for (BasicProfile basicProfile : basicProfiles) {
					FriendLoginData data = new FriendLoginData();
					BeanUtils.copyProperties(basicProfile, data);
					friendsData.add(data);
				}
			}
		}
		
		return friendsData;
	}
	
	/**
	 * add friends
	 * 
	 * URL example:
	 * http://localhost:8080/godating/relationship/userFriend/100000/[100001,100002,10003]
	 * 
	 * @param userId
	 * @param friendIds friendIds is JSON ["111","222", "333", ...]
	 * @param request
	 * @param response
	 */
	@RequestMapping(value = "/userFriend/{userId}/{friendIds}", method = RequestMethod.POST)
	public void addFriends(@PathVariable("userId") String userId, @PathVariable("friendIds") String friendIds, HttpServletRequest request, HttpServletResponse response) {
		Long userIdl = convertString2Long(userId);
		if (userIdl == null) {
			return;
		}
		
		@SuppressWarnings("unchecked")
		ArrayList<String> userIds = JsonMarshaller.unmarshall(friendIds, ArrayList.class, String.class);
		if (userIds != null) {
			Set<Long> friends = new HashSet<Long>();
			for (String id : userIds) {
				Long friendId =  convertString2Long(id);
				if (friendId != null) {
					friends.add(friendId);
				}				
				if (CollectionUtils.isNotEmpty(friends)) {					
					relationshipService.addFriendShips(userIdl, SnsProvider.GODATING, friends);
				}
			}
		}
	}
	
	/**
	 * delete the users all friend relationship
	 * 
	 * @param userId
	 * @param request
	 * @param response
	 */
	@RequestMapping(value = "/userFriend/{userId}", method = RequestMethod.DELETE)
	public void removeFriends(@PathVariable("userId") String userId, HttpServletRequest request, HttpServletResponse response) {
		Long userIdl = convertString2Long(userId);
		if (userIdl == null) {
			return;
		}
		
		relationshipService.deleteFriendShips(userIdl);
	}
	
	/**
	 * delete the user selected friends
	 * 
	 * @param userId
	 * @param request
	 * @param response
	 */
	@RequestMapping(value = "/userFriend/{userId}/{friendIds}", method = RequestMethod.DELETE)
	public void removeFriends(@PathVariable("userId") String userId, @PathVariable("friendIds") String friendIds, HttpServletRequest request, HttpServletResponse response) {
		Long userIdl = convertString2Long(userId);
		if (userIdl == null) {
			return;
		}
		@SuppressWarnings("unchecked")
		ArrayList<String> userIds = JsonMarshaller.unmarshall(friendIds, ArrayList.class, String.class);
		if (userIds != null) {
			Set<Long> friends = new HashSet<Long>();
			for (String id : userIds) {
				Long friendId =  convertString2Long(id);
				if (friendId != null) {
					friends.add(friendId);
				}				
				if (CollectionUtils.isNotEmpty(friends)) {
					relationshipService.deleteFriendShips(userIdl, friends);
				}
			}
		}
		
	}
	
	/**
	 * update the user's friends
	 * 
	 * @param userId
	 * @param friendIds
	 * @param request
	 * @param response
	 */
	@RequestMapping(value = "/userFriend/{userId}/{friendIds}", method = RequestMethod.PUT)
	public void updateFriends(@PathVariable("userId") String userId, @PathVariable("friendIds") String friendIds, HttpServletRequest request, HttpServletResponse response) {
		Long userIdl = convertString2Long(userId);
		if (userIdl == null) {
			return;
		}
		
		@SuppressWarnings("unchecked")
		ArrayList<String> userIds = JsonMarshaller.unmarshall(friendIds, ArrayList.class, String.class);
		if (userIds != null) {
			Set<Long> friends = new HashSet<Long>();
			for (String id : userIds) {
				Long friendId =  convertString2Long(id);
				if (friendId != null) {
					friends.add(friendId);
				}				
				if (CollectionUtils.isNotEmpty(friends)) {					
					relationshipService.updateFriendShips(userIdl, SnsProvider.GODATING, friends);
				}
			}
		}
	}
	
	/**
	 * convert the string to the long type, if any exception, it will return null.
	 * 
	 * @param s
	 */
	private Long convertString2Long(String s) {
		if (s == null) {
			return null;
		}
		Long l = null;
		try {
			l = Long.valueOf(s);
		} catch (Exception e) {
			return null;
		}
		
		return l;
	}

}
